package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// 中间件就是一个HandlerFunc

func indexHandler(context *gin.Context) {
	// gin中间件中使用goroutine
	go aaa(context.Copy()) // 当在中间件或handler中启动新的goroutine时，不能使用原始的上下文（context *gin.Context），必须使用其只读副本（context.Copy()）。
	fmt.Println("index...")
	lalala, ok := context.Get("name") // 在这个中间件接收值
	if !ok {
		fmt.Println(lalala)
	}
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}
func aaa(context *gin.Context) {

}

// 定义中间件
func m1(context *gin.Context) {
	fmt.Println("m1 in ...")
	// 计时
	start := time.Now()
	//context.Next() // 调用后续处理函数
	context.Abort() // 阻止调用后续处理的中间件，直接接着往下执行
	cost := time.Since(start)
	fmt.Println("耗时：", cost)
	fmt.Println("m1 out ...")
	context.Set("name", "lalala") // 中间件直接互相传值
}

// 一般中间件以闭包形式写的
func authMiddleware(doCheck bool) gin.HandlerFunc {
	// 这里写一些比如连接数据库等操作的准备工作
	return func(context *gin.Context) {
		// 这里写具体逻辑
		if doCheck {

		} else {
			context.Next()
		}
	}
}

func main() {
	//r := gin.Default()
	//gin.Default()默认使用了Logger和Recovery中间件，其中：
	// Logger中间件将日志写入gin.DefaultWriter，即使配置了GIN_MODE=release。
	// Recovery中间件会recover任何panic。如果有panic的话，会写入500响应码。
	//如果不想使用上面两个默认的中间件，可以使用gin.New()新建一个没有任何默认中间件的路由。
	r := gin.New()

	//r.GET("/index", func(context *gin.Context) {})
	// GET的参数就是func(context *gin.Context) 类型，所以可以写在外面，然后再传进来
	//r.GET("/index", m1, indexHandler) // m1中间件在前面，所以先走m1先打印
	//r.GET("/shop", m1, func(context *gin.Context) {
	//	context.JSON(http.StatusOK, gin.H{"msg": "shop"})
	//})
	//r.GET("/user", m1, func(context *gin.Context) {
	//	context.JSON(http.StatusOK, gin.H{"msg": "user"})
	//})

	// 上面写法：3个路由都用到了m1中间件，可以使用全局注册，如下写法：
	// 可以写入多个中间件注册
	r.Use(m1, authMiddleware(true))

	r.GET("/index", indexHandler)
	r.GET("/shop", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "shop"})
	})
	r.GET("/user", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "user"})
	})

	//// 写个路由组使用中间件,方式1：
	//xxGroup := r.Group("/xx", authMiddleware(true))
	//{
	//	xxGroup.GET("/index", func(context *gin.Context) {
	//		context.JSON(http.StatusOK, gin.H{"msg": "xxGroup"})
	//	})
	//}
	//// 写个路由组使用中间件,方式2：
	//xx2Group := r.Group("/xx")
	//xx2Group.Use(authMiddleware(true))
	//{
	//	xx2Group.GET("/index", func(context *gin.Context) {
	//		context.JSON(http.StatusOK, gin.H{"msg": "xx2Group"})
	//	})
	//}

	r.Run(":9090")
}
